package main

import (
    "encoding/binary"
    "fmt"
    "net"
    "time"
)

const (
    IEC104_PORT = 2404
)

type IEC104Message struct {
    Type    string
    Data    string
    AuthKey string
}

// 修改：扩展IEC104Message的类型定义，支持新的命令类型
const (
    TYPE_GENERAL_INTERROGATION = "G"
    TYPE_PULSE_INTERROGATION   = "PULSE" // 新增：电能脉冲召唤命令类型
)

func sendIEC104Message(conn net.Conn, message IEC104Message) error {
    data := fmt.Sprintf("%s|%s|%s", message.Type, message.Data, message.AuthKey)
    _, err := conn.Write([]byte(data))
    return err
}

func receiveIEC104Message(conn net.Conn) (IEC104Message, error) {
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        return IEC104Message{}, err
    }
    parts := string(buffer[:n])
    data := parts[:len(parts)-1]
    return IEC104Message{
        Type:    data[0:1],
        Data:    data[2:4],
        AuthKey: data[5:],
    }, nil
}

// 修改函数：解析APDU，增加对32比特串的处理
func parseAPDU(apdu []byte) (map[string]interface{}, error) {
    result := make(map[string]interface{})
    
    // 解析APCI（应用层控制信息）
    apci := apdu[0:2]
    apciType := apci[0] >> 5
    result["apciType"] = apciType
    
    // 根据APCI类型解析更多信息
    switch apciType {
    case 0: // StartDT
        result["startDT"] = true
    case 1: // StopDT
        result["stopDT"] = true
    case 2: // TestFR
        result["testFR"] = true
    case 3: // TestFRCon
        result["testFRCon"] = true
    case 4: // StopDTCon
        result["stopDTCon"] = true
    case 5: // StartDTCon
        result["startDTCon"] = true
    case 6: // I-format
        // 解析I-format报文
        result["format"] = "I-format"
        
        // 解析启动位和确认位
        startBit := (apci[0] & 0x20) >> 5
        confirmBit := (apci[0] & 0x10) >> 4
        result["startBit"] = startBit == 1
        result["confirmBit"] = confirmBit == 1
        
        // 解析传输原因
        transferReason := apci[1]
        result["transferReason"] = transferReason
        
        // 解析ASDU（应用服务数据单元）
        asdu := apdu[2:]
        result["asduLength"] = len(asdu)
        
        // 解析公共地址
        commonAddress := binary.BigEndian.Uint16(asdu[0:2])
        result["commonAddress"] = commonAddress
        
        // 解析信息对象地址
        informationObjectAddress := binary.BigEndian.Uint16(asdu[2:4])
        result["informationObjectAddress"] = informationObjectAddress
        
        // 解析信息对象
        informationObject := asdu[4:]
        result["informationObject"] = informationObject
        
        // 处理归一化值
        if len(informationObject) >= 2 && transferReason == 34 { // 假设传输原因34表示归一化值
            // 解析归一化值
            normalizedValue := binary.BigEndian.Uint16(informationObject[0:2])
            result["normalizedValue"] = normalizedValue
            result["type"] = "normalizedMeasurement"
        }

        // 处理单点信息
        if len(informationObject) >= 2 {
            // 第一个字节的高7位表示信息对象地址
            ioa := binary.BigEndian.Uint16(informationObject[:2]) >> 1
            result["informationObjectAddress"] = ioa
            
            // 第一个字节的最低位表示品质描述符
            quality := informationObject[1] & 0x01
            result["quality"] = quality
            
            // 第二个字节表示状态值
            value := informationObject[2]
            result["value"] = value
            
            // 判断是单点遥信还是单点遥控
            if transferReason == 30 { // 单点遥信
                result["type"] = "singlePointTeleSignal"
            } else if transferReason == 45 { // 单点遥控
                result["type"] = "singlePointRemoteControl"
            }
        }

        // 处理双点信息
        if len(informationObject) >= 3 {
            // 第一个字节的高7位表示信息对象地址
            ioa := binary.BigEndian.Uint16(informationObject[:2]) >> 1
            result["informationObjectAddress"] = ioa
            
            // 第一个字节的最低位表示品质描述符
            quality := informationObject[1] & 0x01
            result["quality"] = quality
            
            // 第二个字节表示状态值
            value := informationObject[2]
            result["value"] = value
            
            // 判断是双点遥信还是双点遥控
            if transferReason == 31 { // 双点遥信
                result["type"] = "doublePointTeleSignal"
            } else if transferReason == 46 { // 双点遥控
                result["type"] = "doublePointRemoteControl"
            }
            
            // 解析双点状态
            switch value {
            case 0:
                result["status"] = "off"
            case 1:
                result["status"] = "on"
            case 2:
                result["status"] = "invalid"
            case 3:
                result["status"] = "indeterminate"
            default:
                result["status"] = "unknown"
            }
        }

        // 处理步位置信息
        if len(informationObject) >= 4 {
            // 第一个字节的高7位表示信息对象地址
            ioa := binary.BigEndian.Uint16(informationObject[:2]) >> 1
            result["informationObjectAddress"] = ioa
            
            // 第一个字节的最低位表示品质描述符
            quality := informationObject[1] & 0x01
            result["quality"] = quality
            
            // 第二个字节表示状态值
            value := informationObject[2]
            result["value"] = value
            
            // 第三个字节表示步位置信息
            stepPosition := informationObject[3]
            result["stepPosition"] = stepPosition
            
            // 判断是步位置遥信还是步位置遥控
            if transferReason == 32 { // 步位置遥信
                result["type"] = "stepPositionTeleSignal"
            } else if transferReason == 47 { // 步位置遥控
                result["type"] = "stepPositionRemoteControl"
            }
        }

        // 处理累计值
        if len(informationObject) >= 6 && transferReason == 36 { // 假设传输原因36表示累计值
            // 解析累计值
            cumulativeValue := binary.BigEndian.Uint32(informationObject[2:6])
            result["cumulativeValue"] = cumulativeValue
            result["type"] = "cumulativeMeasurement"
        }

        // 处理带状态检出的成组单点信息
        if len(informationObject) >= 4 && transferReason == 37 { // 假设传输原因37表示带状态检出的成组单点信息
            // 解析信息对象地址
            ioa := binary.BigEndian.Uint16(informationObject[:2])
            result["informationObjectAddress"] = ioa
            
            // 解析状态检出位和单点信息
            statusWithCheck := informationObject[2:]
            var singlePoints []map[string]interface{}
            for i := 0; i < len(statusWithCheck); i++ {
                singlePoint := make(map[string]interface{})
                
                // 状态检出位（最高位）
                statusCheck := (statusWithCheck[i] & 0x80) >> 7
                singlePoint["statusCheck"] = statusCheck == 1
                
                // 单点信息（低7位）
                singlePointValue := statusWithCheck[i] & 0x7F
                singlePoint["value"] = singlePointValue
                
                // 解析单点状态
                switch singlePointValue {
                case 0:
                    singlePoint["status"] = "off"
                case 1:
                    singlePoint["status"] = "on"
                default:
                    singlePoint["status"] = "unknown"
                }
                
                singlePoints = append(singlePoints, singlePoint)
            }
            result["singlePoints"] = singlePoints
            result["type"] = "groupedSinglePointWithStatusCheck"
        }

        // 新增：处理归一化测量值
        if len(informationObject) >= 4 && transferReason == 34 { // 假设传输原因34表示归一化测量值
            // 解析归一化测量值
            normalizedValue := binary.BigEndian.Uint16(informationObject[2:4])
            result["normalizedValue"] = normalizedValue
            result["type"] = "normalizedMeasurement"
        }

        // 新增：处理不带品质描述的归一化测量值
        if len(informationObject) >= 2 && transferReason == 34 { // 假设传输原因34表示不带品质描述的归一化测量值
            // 解析归一化测量值
            normalizedValue := binary.BigEndian.Uint16(informationObject[0:2])
            result["normalizedValue"] = normalizedValue
            result["type"] = "normalizedMeasurementWithoutQuality"
        }

        // 新增：处理32比特串
        if len(informationObject) >= 6 && transferReason == 33 { // 假设传输原因33表示32比特串
            // 解析32比特串
            bitString := binary.BigEndian.Uint32(informationObject[2:6])
            result["bitString"] = bitString
            result["type"] = "32BitString"
        }

        // 新增：处理浮点型测量值
        if len(informationObject) >= 6 && transferReason == 35 { // 假设传输原因35表示浮点型测量值
            // 解析浮点型测量值
            floatValue := float32(binary.BigEndian.Uint32(informationObject[2:6]))
            result["floatValue"] = floatValue
            result["type"] = "floatMeasurement"
        }

        // 新增：处理短浮点值
        if len(informationObject) >= 6 && transferReason == 35 { // 假设传输原因35表示短浮点值
            // 解析短浮点值
            floatValue := float32(binary.BigEndian.Uint32(informationObject[2:6]))
            result["floatValue"] = floatValue
            result["type"] = "shortFloatMeasurement"
        }

    case 7: // S-format
        // 解析S-format报文
        result["format"] = "S-format"
        
        // 解析启动位和确认位
        startBit := (apci[0] & 0x20) >> 5
        confirmBit := (apci[0] & 0x10) >> 4
        result["startBit"] = startBit == 1
        result["confirmBit"] = confirmBit == 1
        
        // 解析发送序列号（Send Sequence Number, SN）
        sn := (apci[0] & 0x0F) << 1 | (apci[1] & 0x80) >> 7
        result["sendSequenceNumber"] = sn
        
        // 解析接收序列号（Receive Sequence Number, RN）
        rn := (apci[1] & 0x7F)
        result["receiveSequenceNumber"] = rn
        
    case 8: // U-format
        // 解析U-format报文
        result["format"] = "U-format"
        
        // 解析功能码（Function Code）
        functionCode := apci[0] & 0x0F
        result["functionCode"] = functionCode
        
    default:
        return nil, fmt.Errorf("unknown APCI type: %d", apciType)
    }
    
    return result, nil
}

// 新增函数：构建APDU
func buildAPDU(apciType uint8, commonAddress uint16, informationObjectAddress uint16, informationObject []byte) ([]byte, error) {
    apdu := make([]byte, 2+len(informationObject)+4)
    
    // 构建APCI
    apci := make([]byte, 2)
    apci[0] = apciType << 5
    apci[1] = 0
    copy(apdu[0:2], apci)
    
    // 构建ASDU公共地址
    binary.BigEndian.PutUint16(apdu[2:4], commonAddress)
    
    // 构建信息对象地址
    binary.BigEndian.PutUint16(apdu[4:6], informationObjectAddress)
    
    // 构建信息对象
    copy(apdu[6:], informationObject)
    
    return apdu, nil
}